﻿using BBCore.Application.Interface;
using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace BBCore.Application.Service
{
    public class ClosedxmlExcelExportService : IClosedxmlExcelExportService
    {
        /// <summary>
        /// 导出单个工作表的 Excel 文件。
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="data">要导出的数据列表</param>
        /// <param name="sheetName">工作表名称</param>
        /// <param name="columns">列头及选择器元组，包含列头名称和数据选择器</param>
        /// <returns>返回生成的 Excel 工作簿</returns>
        public IXLWorkbook ExportSingleSheet<T>(
            List<T> data,
            string sheetName,
            List<(string Header, Func<T, object> Selector)> columns)
        {
            // 创建工作簿并添加工作表
            var workbook = new XLWorkbook();
            var sheet = workbook.Worksheets.Add(sheetName);

            int row = 1;

            // 写列头
            for (int i = 0; i < columns.Count; i++)
            {
                sheet.Cell(row, i + 1).Value = columns[i].Header;
                sheet.Cell(row, i + 1).Style.Font.Bold = true;  // 设置字体为加粗
            }

            // 填充数据
            foreach (var item in data)
            {
                row++;
                for (int i = 0; i < columns.Count; i++)
                {
                    var value = columns[i].Selector(item);
                    sheet.Cell(row, i + 1).SetValue(value != null ? value.ToString() : "");
                }
            }

            // 格式设置，自动调整列宽，冻结表头行
            sheet.Columns().AdjustToContents();
            sheet.SheetView.FreezeRows(1);

            // 只有当工作表有数据时，才设置自动筛选
            var range = sheet.RangeUsed();
            if (range != null)
            {
                range.SetAutoFilter();
            }

            return workbook;  // 返回生成的工作簿
        }

        /// <summary>
        /// 导出主从结构的 Excel 文件，支持 Master-Detail 数据结构。
        /// </summary>
        /// <typeparam name="TMaster">主数据类型</typeparam>
        /// <typeparam name="TDetail">明细数据类型</typeparam>
        /// <param name="masters">主数据列表</param>
        /// <param name="detailSelector">从主数据获取明细数据的选择器函数</param>
        /// <param name="sheetName">工作表名称</param>
        /// <param name="masterColumns">主表列头及选择器元组</param>
        /// <param name="detailColumns">明细表列头及选择器元组</param>
        /// <returns>返回生成的 Excel 工作簿</returns>
        public IXLWorkbook ExportMasterDetail<TMaster, TDetail>(
            List<TMaster> masters,
            Func<TMaster, List<TDetail>> detailSelector,
            string sheetName,
            List<(string Header, Func<TMaster, object>)> masterColumns,
            List<(string Header, Func<TDetail, object>)> detailColumns)
        {
            // 创建工作簿并添加工作表
            var workbook = new XLWorkbook();
            var sheet = workbook.Worksheets.Add(sheetName);

            int row = 1;
            int col = 1;

            // 写主表列头
            foreach (var (header, _) in masterColumns)
            {
                sheet.Cell(row, col).Value = header;
                sheet.Cell(row, col).Style.Font.Bold = true;  // 设置字体为加粗
                col++;
            }

            // 写明细表列头
            foreach (var (header, _) in detailColumns)
            {
                sheet.Cell(row, col).Value = header;
                sheet.Cell(row, col).Style.Font.Bold = true;  // 设置字体为加粗
                col++;
            }

            // 填充数据
            foreach (var master in masters)
            {
                var details = detailSelector(master) ?? new List<TDetail>();  // 获取主数据对应的明细数据
                int detailCount = Math.Max(1, details.Count);  // 如果没有明细数据，设为1行
                int startRow = row + 1;

                for (int i = 0; i < detailCount; i++)
                {
                    row++;
                    var detail = i < details.Count ? details[i] : default;

                    // 填充主表数据
                    for (int j = 0; j < masterColumns.Count; j++)
                    {
                        var value = masterColumns[j].Item2(master);
                        sheet.Cell(row, j + 1).SetValue(value != null ? value.ToString() : "");
                    }

                    // 填充明细表数据
                    for (int j = 0; j < detailColumns.Count; j++)
                    {
                        var value = detail != null ? detailColumns[j].Item2(detail) : null;
                        sheet.Cell(row, masterColumns.Count + j + 1).SetValue(value != null ? value.ToString() : "");
                    }
                }

                // 合并主表数据列，使其垂直居中，   如何不合并单元格版本把这段循环注释掉或删掉即可
                for (int j = 1; j <= masterColumns.Count; j++)
                    sheet.Range(startRow, j, row, j).Merge().Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;

                // 如果有多行明细，进行分组
                if (detailCount > 1)
                    sheet.Rows(startRow, row).Group();
            }

            // 格式设置，自动调整列宽，冻结表头行
            sheet.Columns().AdjustToContents();
            sheet.SheetView.FreezeRows(1);

            // 只有当工作表有数据时，才设置自动筛选
            var range2 = sheet.RangeUsed();
            if (range2 != null)
            {
                range2.SetAutoFilter();
            }

            return workbook;  // 返回生成的工作簿
        }

        /// <summary>
        /// 自动导出主从结构（Master-Detail）的 Excel 表格，无需手动指定列头和选择器。
        /// </summary>
        /// <typeparam name="TMaster">主表实体类型，例如 PurchaseOrder。</typeparam>
        /// <typeparam name="TDetail">明细表实体类型，例如 OrderDetail。</typeparam>
        /// <param name="masters">主表数据列表。</param>
        /// <param name="detailSelector">
        /// 用于从主表对象中提取明细数据的函数，通常为 <c>o => o.Details</c>。
        /// </param>
        /// <param name="sheetName">工作表名称。</param>
        /// <returns>返回构建好的 Excel 工作簿（IXLWorkbook）。</returns>
        /// <remarks>
        /// - 自动获取 <typeparamref name="TMaster"/> 和 <typeparamref name="TDetail"/> 的属性作为列；
        ///— 如果属性有<see cref="System.ComponentModel.DataAnnotations.DisplayAttribute"/>，将使用其中的<c> Name</c> 作为列头；
        ///— 否则默认使用属性名称；
        ///— 主表中包含集合类型的属性（如 List<OrderDetail>）将被忽略，仅导出基本字段。
        /// </remarks>
        public IXLWorkbook ExportMasterDetailAuto<TMaster, TDetail>(
            List<TMaster> masters,
            Func<TMaster, List<TDetail>> detailSelector,
            string sheetName)
        {
            // 生成主表列头和选择器
            var masterColumns = typeof(TMaster)
                .GetProperties()
                .Where(p => !typeof(System.Collections.IEnumerable).IsAssignableFrom(p.PropertyType) || p.PropertyType == typeof(string)) // 忽略集合属性
                .Select(p => (
                    Header: p.GetCustomAttribute<DisplayAttribute>()?.Name ?? p.Name,
                    Selector: (Func<TMaster, object>)(m =>
                    {
                        var value = p.GetValue(m);
                        // 如果值为null，返回默认值（如""，也可以是其他类型的默认值）
                        return value ?? string.Empty;  // 或者可以用 `return value ?? 0;` 或者其他默认值
                    })
                ))
                .ToList();

            // 生成明细表列头和选择器
            var detailColumns = typeof(TDetail)
                .GetProperties()
                .Select(p => (
                    Header: p.GetCustomAttribute<DisplayAttribute>()?.Name ?? p.Name,
                     Selector: (Func<TDetail, object>)(d =>
                     {
                         var value = p.GetValue(d);
                         // 如果值为null，返回默认值（如""，也可以是其他类型的默认值）
                         return value ?? string.Empty;  // 或者可以用 `return value ?? 0;` 或者其他默认值
                     })
                ))
                .ToList();

            // 调用原始的 ExportMasterDetail 方法生成最终的工作簿
            return ExportMasterDetail(masters, detailSelector, sheetName, masterColumns, detailColumns);
        }

    }
}
